home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / perl5 / Apache / RPC / Status.pm < prev    next >
Encoding:
Perl POD Document  |  2008-04-10  |  35.1 KB  |  981 lines

  1. ###############################################################################
  2. #
  3. # This file copyright (c) 2001-2008 Randy J. Ray, all rights reserved
  4. #
  5. # See "LICENSE" in the documentation for licensing and redistribution terms.
  6. #
  7. ###############################################################################
  8. #
  9. #   $Id: Status.pm 343 2008-04-09 09:54:36Z rjray $
  10. #
  11. #   Description:    This module is intended to provide a browser-friendly
  12. #                   status page on the RPC server(s) being managed by the
  13. #                   hosting Apache process.
  14. #
  15. #                   Some parts of this are borrowed from the Apache::Status
  16. #                   module.
  17. #
  18. #   Functions:      new
  19. #                   version
  20. #                   handler
  21. #                   init_handler
  22. #                   apache_status_attach
  23. #                   header
  24. #                   footer
  25. #                   make_url
  26. #                   main_screen
  27. #                   server_summary
  28. #                   server_detail
  29. #                   method_summary
  30. #                   method_detail
  31. #
  32. #   Libraries:      Apache
  33. #                   Apache::Constants
  34. #
  35. #   Global Consts:  $Apache::RPC::Status::VERSION
  36. #
  37. #   Environment:    None.
  38. #
  39. ###############################################################################
  40.  
  41. package Apache::RPC::Status;
  42.  
  43. use 5.005;
  44. use strict;
  45. use vars qw(%IS_INSTALLED $SERVER_VER $STARTED $PERL_VER $DEFAULT $SERVER_CLASS
  46.             %proto $newQ);
  47. use subs qw(header footer main_screen server_summary server_detail
  48.             method_summary method_detail);
  49.  
  50. use Apache;
  51. use Apache::Constants qw(DECLINED OK SERVER_VERSION);
  52. use CGI;
  53.  
  54. # We use the server module to get the class methods for server objects, etc.
  55. require Apache::RPC::Server;
  56. require RPC::XML::Method;
  57.  
  58. #$SERVER_VER = SERVER_VERSION;
  59. $SERVER_CLASS = 'Apache::RPC::Server';
  60. $STARTED    = scalar localtime $^T;
  61. $PERL_VER   = $^V ? sprintf "v%vd", $^V : $];
  62.  
  63. $Apache::RPC::Status::VERSION = '1.07';
  64.  
  65. #
  66. # %proto is the prototype set of screens/handlers that this class knows about.
  67. # It is used in new() to initialize the hash table.
  68. #
  69. %proto = ( main   => { title => 'Main Screen', call => \&main_screen },
  70.            server => { title => 'Server Detail Screen',
  71.                        call => \&server_detail },
  72.            method => { title => 'Method Detail Screen',
  73.                        call => \&method_detail } );
  74.  
  75. # This is an artifact, but things don't seem to work without it
  76. $newQ = sub { CGI->new; };
  77.  
  78. #
  79. # This next bit graciously "borrowed" from Apache::Status
  80. #
  81. my %IS_INSTALLED = ();
  82. {
  83.     local $SIG{__DIE__};
  84.     %IS_INSTALLED = map {
  85.         $_, (eval("require $_") || 0);
  86.     } qw(Data::Dumper Devel::Symdump B Apache::Request Apache::Peek
  87.          Apache::Symbol);
  88. }
  89.  
  90. # Simple token-response method
  91. sub version { $Apache::RPC::Status::VERSION }
  92.  
  93. sub new
  94. {
  95.     my $class = shift;
  96.     my @args  = @_;
  97.  
  98.     my %self = %proto;
  99.     $class = ref($class) || $class;
  100.  
  101.     bless \%self, $class;
  102. }
  103.  
  104. # This retrieves the default object for use within handler() below. Basically,
  105. # handler() needs a blessed reference to operate on so that it can call the
  106. # header() and footer() routines as methods to allow for subclassing.
  107. sub default_object
  108. {
  109.     return $DEFAULT if (ref $DEFAULT);
  110.  
  111.     $DEFAULT = shift->new(@_);
  112. }
  113.  
  114. ###############################################################################
  115. #
  116. #   Sub Name:       handler
  117. #
  118. #   Description:    This is the basic entry point for the majority of uses
  119. #                   for this module. It handles requests at the usual content
  120. #                   phase of the request cycle.
  121. #
  122. #   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION
  123. #                   $self     in      scalar    Either a class name (if static)
  124. #                                                 or a reference
  125. #                   $r        in      Apache    The request object
  126. #
  127. #   Returns:        Apache code (either OK or DECLINED)
  128. #
  129. ###############################################################################
  130. sub handler ($$)
  131. {
  132.     my $self = shift;
  133.     my $r    = shift;
  134.  
  135.     my ($qs, $pick, %args);
  136.  
  137.     $self = $self->default_object() unless ref($self);
  138.     $qs = $newQ->($r);
  139.     $pick = $qs->param('screen') || 'main';
  140.     # One last check
  141.     return DECLINED unless exists $self->{$pick};
  142.  
  143.     $self->header($r, $self->{$pick}{title});
  144.     $r->print(@{$self->{$pick}{call}->($self, $r, $qs)});
  145.     $self->footer($r);
  146.  
  147.     OK;
  148. }
  149.  
  150. ###############################################################################
  151. #
  152. #   Sub Name:       init_handler
  153. #
  154. #   Description:    Perform any child-proc-specific initialization. Must be
  155. #                   set as a PerlChildInitHandler.
  156. #
  157. #   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION
  158. #                   $class    in      scalar    Class or handler reference
  159. #                   $r        in      Apache    Request object
  160. #
  161. #   Globals:        $SERVER_CLASS
  162. #
  163. #   Returns:        Apache code (currently always OK)
  164. #
  165. ###############################################################################
  166. sub init_handler ($$)
  167. {
  168.     my ($class, $r) = @_;
  169.  
  170.     my $val;
  171.  
  172.     $SERVER_CLASS = $val if ($val = $r->dir_config('ServerClass'));
  173.  
  174.     OK;
  175. }
  176.  
  177. ###############################################################################
  178. #
  179. #   Sub Name:       apache_status_attach
  180. #
  181. #   Description:    Attach to the Apache::Status mechanism, if possible. The
  182. #                   object that calls this method will be used to dispatch
  183. #                   any future requests. That means that there is a dangling
  184. #                   reference to it in the closure that is created here, and
  185. #                   which likely lives somewhere within Apache::Status. Just
  186. #                   in case you some day wonder why your object appears to
  187. #                   linger...
  188. #
  189. #   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION
  190. #                   $self     in      ref       Object reference
  191. #
  192. #   Returns:        void
  193. #
  194. ###############################################################################
  195. sub apache_status_attach
  196. {
  197.     my $self = shift;
  198.  
  199.     my $class = ref($self) || $self;
  200.  
  201.     Apache::Status->
  202.           menu_item(XMLRPC => "$class Monitor",
  203.                     sub {
  204.                         my ($r, $q) = @_; #request and CGI objects
  205.                         my $hook = $q->param('screen') || 'main';
  206.  
  207.                         $self->{$hook}{call}->($self, $r, $q, 1);
  208.                     }) if Apache->module('Apache::Status');
  209.  
  210.     return;
  211. }
  212.  
  213. ###############################################################################
  214. #
  215. #   Sub Name:       header
  216. #
  217. #   Description:    Produce the HTML header to start a generic page
  218. #
  219. #   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION
  220. #                   $self     in      ref       Class object
  221. #                   $r        in      ref       Apache request object
  222. #                   $title    in      scalar    If passed, extra text for the
  223. #                                                 title
  224. #
  225. #   Globals:        $SERVER_VER
  226. #                   $STARTED
  227. #                   $PERL_VER
  228. #
  229. #   Returns:        void
  230. #
  231. ###############################################################################
  232. sub header
  233. {
  234.     my ($self, $r, $title) = @_;
  235.  
  236.     $SERVER_VER = SERVER_VERSION unless ($SERVER_VER);
  237.  
  238.     $title = " - $title" if $title;
  239.     $title = (ref($self) || $self) . $title;
  240.  
  241.     $r->send_http_header('text/html');
  242.     $r->print(<<"EOF");
  243. <html>
  244. <head><title>$title</title></head>
  245. <body bgcolor="white">
  246. <p>Perl version <b>$PERL_VER</b> for <b>$SERVER_VER</b> process <b>$$</b>,<br>
  247. running since $STARTED</p>
  248. <hr>
  249. EOF
  250.  
  251.     return;
  252. }
  253.  
  254. ###############################################################################
  255. #
  256. #   Sub Name:       footer
  257. #
  258. #   Description:    Close out the current HTML page
  259. #
  260. #   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION
  261. #                   $self     in      ref       Class object
  262. #                   $r        in      ref       Apache request object
  263. #
  264. #   Returns:        void
  265. #
  266. ###############################################################################
  267. sub footer
  268. {
  269.     my ($self, $r) = @_;
  270.  
  271.     my $name = ref($self) || $self;
  272.     my $vers = $self->version;
  273.     my $date = scalar localtime;
  274.  
  275.     $r->print(<<"EOF");
  276. <hr>
  277. <table width="100%">
  278. <tr>
  279. <td><i>$name $vers</i></td>
  280. <td align="right">$date</td>
  281. </tr>
  282. </table>
  283. </body>
  284. </html>
  285. EOF
  286.  
  287.     return;
  288. }
  289.  
  290. ###############################################################################
  291. #
  292. #   Sub Name:       make_url
  293. #
  294. #   Description:    Simple url-generation routine that preserves params from
  295. #                   the CGI (or Apache) object, and pays attention to whether
  296. #                   the URL should be patterned for use under Apache::Status
  297. #
  298. #   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION
  299. #                   $class    in      scalar    Class, ignored
  300. #                   $query    in      ref       Query or Apache object ref
  301. #                   $flag     in      scalar    If passed and true, create a
  302. #                                                 URI for Apache::Status
  303. #
  304. #   Returns:        string
  305. #
  306. ###############################################################################
  307. sub make_url
  308. {
  309.     my ($class, $query, $flag) = @_;
  310.  
  311.     $query = $newQ->($query) unless (ref($query) eq 'CGI');
  312.  
  313.     my @params = map {
  314.         ($_ eq 'keywords') ? () : "$_=" . $query->param($_)
  315.     } ($query->param());
  316.     my $text = $query->url(-path => 1) . '?';
  317.  
  318.     unshift(@params, 'RPCXML') if ($flag);
  319.     $text .= join('&', @params);
  320.  
  321.     $text;
  322. }
  323.  
  324. ###############################################################################
  325. #
  326. #   Sub Name:       main_screen
  327. #
  328. #   Description:    Produce the HTML body for the main status screen.
  329. #
  330. #   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION
  331. #                   $self     in      ref       Object of this class
  332. #                   $R        in      ref       Apache object reference
  333. #                   $Q        in      CGI       Query object
  334. #                   $flag     in      scalar    If passed and true, this means
  335. #                                                 that the call is coming from
  336. #                                                 within Apache::Status
  337. #
  338. #   Globals:        $SERVER_CLASS
  339. #
  340. ###############################################################################
  341. sub main_screen
  342. {
  343.     my ($self, $R, $Q, $flag) = @_;
  344.  
  345.     my (@servers, $server, $uri, @lines);
  346.  
  347.     # Set (or override) the param value for 'screen' before calling make_url
  348.     $Q->param(-name => 'screen', -value => 'server');
  349.     $uri = $self->make_url($Q, $flag);
  350.     @servers = sort $SERVER_CLASS->list_servers();
  351.  
  352.     push(@lines, $Q->p($Q->b('Apache XML-RPC Status Monitor')));
  353.     push(@lines, sprintf("<p>There %s %d server%s configured:</p>",
  354.                          (@servers == 1) ?
  355.                          ('is', 1, '') : ('are', scalar(@servers), 's')));
  356.     push(@lines,
  357.          $Q->table({ -cellpadding => 15, -width => '75%', -border => 0 },
  358.                    (map {
  359.                        ($server = $_) =~ s/</</g;
  360.  
  361.                        $Q->TR({ -valign => 'top' },
  362.                               $Q->td({ -width => '35%' },
  363.                                      # I'm adding server=n here to avoid extra
  364.                                      # calls to make_url()
  365.                                      $Q->a({ -href => "$uri&server=$_" },
  366.                                            $server)),
  367.                               $Q->td(server_summary($Q,
  368.                                                     $SERVER_CLASS->
  369.                                                     get_server($_))));
  370.                    } (@servers))));
  371.  
  372.     \@lines;
  373. }
  374.  
  375. ###############################################################################
  376. #
  377. #   Sub Name:       server_summary
  378. #
  379. #   Description:    Produce the summary table of server info for the main
  380. #                   status page.
  381. #
  382. #   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION
  383. #                   $Q        in      CGI       Query object (for HTML bits)
  384. #                   $srv      in      ref       Server object reference
  385. #
  386. #   Returns:        text chunk
  387. #
  388. ###############################################################################
  389. sub server_summary
  390. {
  391.     my ($Q, $srv) = @_;
  392.  
  393.     $Q->table($Q->TR({ -valign => 'top' },
  394.                      $Q->td($Q->b($Q->tt('URI:'))),
  395.                      $Q->td($srv->url())),
  396.               $Q->TR({ -valign => 'top' },
  397.                      $Q->td($Q->b($Q->tt('Requests:'))),
  398.                      $Q->td($srv->requests())),
  399.               $Q->TR({ -valign => 'top' },
  400.                      $Q->td($Q->b($Q->tt('Started:'))),
  401.                      $Q->td(scalar localtime $srv->started())),
  402.               $Q->TR({ -valign => 'top' },
  403.                      $Q->td($Q->b($Q->tt('Available methods:'))),
  404.                      $Q->td(scalar($srv->list_methods))));
  405. }
  406.  
  407. ###############################################################################
  408. #
  409. #   Sub Name:       server_detail
  410. #
  411. #   Description:    Provide a detailed break-down screen for a single
  412. #                   server object.
  413. #
  414. #   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION
  415. #                   $self     in      ref       Object of this class
  416. #                   $R        in      ref       Apache object reference
  417. #                   $Q        in      CGI       Query object
  418. #                   $flag     in      scalar    If passed and true, means that
  419. #                                                 we are called from with the
  420. #                                                 Apache::Status module
  421. #
  422. #   Globals:        $SERVER_CLASS
  423. #
  424. ###############################################################################
  425. sub server_detail
  426. {
  427.     my ($self, $R, $Q, $flag) = @_;
  428.  
  429.     my ($srv, $server, @lines, @methods, $meth1, $meth2, $base_url);
  430.  
  431.     $server = $Q->param('server');
  432.     # Override this before calling make_url:
  433.     $Q->param(-name => 'screen', -value => 'method');
  434.     # Now create the base URL string for method_summary to use
  435.     $base_url = $self->make_url($Q, $flag);
  436.     if (! $server)
  437.     {
  438.         return [ "Error: No server name specified when screen invoked" ];
  439.     }
  440.     elsif (! ref($srv = $SERVER_CLASS->get_server($server)))
  441.     {
  442.         return [ "Error fetching server named $server: $srv" ];
  443.     }
  444.  
  445.     push(@lines, '<div align="center">', $Q->b('Server: '), $Q->tt($server));
  446.     push(@lines, $Q->br(), $Q->br());
  447.     push(@lines, '<table border="0" width="75%">');
  448.     push(@lines, $Q->TR({ -valign => 'top' },
  449.                         $Q->td($Q->b('Server Tokens:')),
  450.                         $Q->td($Q->tt($srv->product_tokens))));
  451.     push(@lines, $Q->TR({ -valign => 'top' },
  452.                         $Q->td($Q->b('Server URL:')),
  453.                         $Q->td($Q->tt($srv->url))));
  454.     push(@lines, $Q->TR({ -valign => 'top' },
  455.                         $Q->td($Q->b('Server Started:')),
  456.                         $Q->td($Q->tt(scalar localtime $srv->started()))));
  457.     push(@lines, $Q->TR({ -valign => 'top' },
  458.                         $Q->td($Q->b('This Child Started:')),
  459.                         $Q->td($Q->tt(scalar localtime $srv->child_started))));
  460.     push(@lines, $Q->TR({ -valign => 'top' },
  461.                         $Q->td($Q->b('Requests Handled:')),
  462.                         $Q->td($Q->tt($srv->requests))));
  463.     push(@lines, $Q->TR({ -valign => 'top' },
  464.                         $Q->td($Q->b('Method Search Path:')),
  465.                         $Q->td($Q->tt(join($Q->br(), @{$srv->xpl_path})))));
  466.     push(@lines, $Q->TR($Q->td({ colspan => 2 }, ' ')));
  467.     @methods = sort $srv->list_methods;
  468.     if (@methods)
  469.     {
  470.         push(@lines, $Q->TR($Q->td({ colspan => 2, -align => 'center' },
  471.                                    $Q->b('Known Methods: '),
  472.                                    sprintf('(%d)', scalar(@methods)))));
  473.         push(@lines, '<tr><td colspan="2"><table width="100%" border="1">');
  474.         while (@methods)
  475.         {
  476.             ($meth1, $meth2) = splice(@methods, 0, 2);
  477.             push(@lines, '<tr valign="top"><td width="50%">');
  478.             push(@lines, method_summary($Q, $server, $srv->get_method($meth1),
  479.                                         $base_url));
  480.             push(@lines, '</td><td width="50%">');
  481.             if ($meth2)
  482.             {
  483.                 push(@lines, method_summary($Q, $server,
  484.                                             $srv->get_method($meth2),
  485.                                             $base_url));
  486.             }
  487.             else
  488.             {
  489.                 push(@lines, ' ');
  490.             }
  491.             push(@lines, '</td></tr>');
  492.         }
  493.         push(@lines, '</table></td></tr>');
  494.     }
  495.     push(@lines, '</table></div>');
  496.  
  497.     \@lines;
  498. }
  499.  
  500. ###############################################################################
  501. #
  502. #   Sub Name:       method_summary
  503. #
  504. #   Description:    Create the HTML table for a method-object summary
  505. #
  506. #   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION
  507. #                   $Q        in      CGI       Query object (for HTML stuff)
  508. #                   $server   in      scalar    Name (ident) of server this
  509. #                                                 method is from
  510. #                   $meth     in      ref       RPC::XML::Method (or deriv.)
  511. #                                                 reference
  512. #                   $base_url in      scalar    Base URL to use when making
  513. #                                                 links
  514. #
  515. #   Returns:        text
  516. #
  517. ###############################################################################
  518. sub method_summary
  519. {
  520.     my ($Q, $server, $meth, $base_url) = @_;
  521.  
  522.     $Q->table({ -width => '100%' },
  523.               $Q->TR({ -valign => 'top' },
  524.                      $Q->td({ -width => '33%' }, $Q->b('Name:')),
  525.                      $Q->td($Q->tt($Q->a({ -href =>
  526.                                            "$base_url&method=" . $meth->name },
  527.                                          $meth->name)))),
  528.               $Q->TR({ -valign => 'top' },
  529.                      $Q->td($Q->b('Version:')),
  530.                      $Q->td($Q->tt($meth->version))),
  531.               $Q->TR({ -valign => 'top' },
  532.                      $Q->td($Q->b('Hidden status:')),
  533.                      $Q->td($Q->tt($meth->hidden() ? 'Hidden' : 'Visible'))),
  534.               $Q->TR({ -valign => 'top' },
  535.                      $Q->td($Q->b('Calls:')),
  536.                      $Q->td($Q->tt($meth->{called} || 0))));
  537. }
  538.  
  539. ###############################################################################
  540. #
  541. #   Sub Name:       method_detail
  542. #
  543. #   Description:    Provide a detailed description and statistics for the
  544. #                   specified method.
  545. #
  546. #   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION
  547. #                   $self     in      ref       Object of this class
  548. #                   $R        in      ref       Apache object reference
  549. #                   $Q        in      CGI       Query object
  550. #                   $flag     in      scalar    If passed and true, means that
  551. #                                                 we are called from with the
  552. #                                                 Apache::Status module
  553. #
  554. #   Globals:        $SERVER_CLASS
  555. #
  556. ###############################################################################
  557. sub method_detail
  558. {
  559.     my ($self, $R, $Q, $flag) = @_;
  560.     # $flag has no relevance in this routine
  561.  
  562.     my ($server, $srv, $method, $meth, $tmp, @lines);
  563.  
  564.     $server = $Q->param('server');
  565.     $method = $Q->param('method');
  566.  
  567.     if (! $server)
  568.     {
  569.         return [ "Error: No server name specified when screen invoked" ];
  570.     }
  571.     elsif (! ref($srv = $SERVER_CLASS->get_server($server)))
  572.     {
  573.         return [ "Error fetching server named $server: $srv" ];
  574.     }
  575.     if (! $method)
  576.     {
  577.         return [ "Error: No method name specified when screen invoked" ];
  578.     }
  579.     elsif (! ref($meth = $srv->get_method($method)))
  580.     {
  581.         return [ "Error: No method named $method found on server $server" ];
  582.     }
  583.  
  584.     push(@lines, '<div align="center">', $Q->b('Method: '), $Q->tt($method));
  585.     push(@lines, $Q->br(), $Q->br());
  586.     push(@lines, '<table border="0" width="75%">');
  587.     push(@lines, $Q->TR({ -valign => 'top' },
  588.                         $Q->td($Q->b('Version:')), $Q->td($Q->tt($tmp))))
  589.         if ($tmp = $meth->version);
  590.     push(@lines, $Q->TR({ -valign => 'top' },
  591.                         $Q->td({ -width => '30%' }, $Q->b('Hidden from API:')),
  592.                         $Q->td($Q->tt($meth->hidden() ? 'Yes' : 'No'))));
  593.     push(@lines, $Q->TR({ -valign => 'top' },
  594.                         $Q->td($Q->b('Calls:')),
  595.                         $Q->td($Q->tt($meth->{called}))));
  596.     if ($meth->{file})
  597.     {
  598.         push(@lines, $Q->TR({ -valign => 'top' },
  599.                             $Q->td($Q->b('Loaded from:')),
  600.                             $Q->td($Q->tt($meth->{file}))));
  601.         push(@lines, $Q->TR({ -valign => 'top' },
  602.                             $Q->td($Q->b('File last updated:')),
  603.                             $Q->td($Q->tt(scalar localtime $meth->{mtime}))));
  604.     }
  605.     push(@lines, $Q->TR({ -valign => 'top' },
  606.                         $Q->td($Q->b('Signatures:')),
  607.                         $Q->td($Q->tt(join('<br>', @{$meth->signature})))));
  608.     if ($tmp = $meth->help)
  609.     {
  610.         push(@lines, $Q->TR($Q->td({ -colspan => 2 }, $Q->b('Help string:'))));
  611.         push(@lines, $Q->TR($Q->td({ -colspan => 2 }, $Q->pre($Q->tt($tmp)))));
  612.     }
  613.     push(@lines, '</table></div>');
  614.  
  615.     \@lines;
  616. }
  617.  
  618. 1;
  619.  
  620. __END__
  621.  
  622. =head1 NAME
  623.  
  624. Apache::RPC::Status - A status monitor similar to Apache::Status for RPC
  625.  
  626. =head1 SYNOPSIS
  627.  
  628.     # In httpd.conf:
  629.     </Location /rpc-status>
  630.         SetHandler perl-script
  631.         PerlHandler Apache::RPC::Status
  632.     </Location>
  633.  
  634.     # In the start-up Perl file:
  635.     use Apache::RPC::Status;
  636.  
  637. =head1 DESCRIPTION
  638.  
  639. The B<Apache::RPC::Status> package is provided as a simple status monitor for
  640. XML-RPC servers running in a B<mod_perl> environment, using the
  641. B<Apache::RPC::Server> class (or derivative of). Patterned after the status
  642. system provided with B<mod_perl> itself, information is broken down into a
  643. series of screens providing information ranging from the RPC servers currently
  644. configured down to the individual methods provided by the servers.
  645.  
  646. =head2 Information Screens
  647.  
  648. There are three basic screens provided by the stock B<Apache::RPC::Status>
  649. package:
  650.  
  651. =over 4
  652.  
  653. =item Main: Listing of Servers
  654.  
  655. This screen is the first screen that comes up when the location for which this
  656. class was assigned as a handler is invoked. It lists the server objects that
  657. this running Apache process knows of. Note that if the servers are defined in
  658. such a way as to mean on-demand creation, then a given child process may not
  659. have all the configured servers in memory. This is by design, it is not a
  660. bug. See L<Apache::RPC::Server/Usage Within E<lt>PerlE<gt> Sections> for
  661. details on configuring the RPC servers such that they are pre-loaded into all
  662. child processes.
  663.  
  664. =item Server: Details of a Server
  665.  
  666. Each of the known servers in the main screen links to this screen, which
  667. provides details on the specific server. Information such as when the server
  668. was started (which usually matches the time that Apache was started), when the
  669. specific child was started (which may not be the same), number of requests
  670. servered, and so forth is provided. Additionally, each of the methods that the
  671. server provides is listed in alphanumeric order, with a link to the next
  672. screen.
  673.  
  674. =item Method: Details of a Specific Method
  675.  
  676. For each of the known methods published by a server, this screen summarizes
  677. all that is known about the method itself. The signatures, help text and
  678. hidden status (whether the method is visible to the introspection API that is
  679. shipped with B<RPC::XML::Server>) are all shown. Some optional information is
  680. shown if available: if the method has a version number associated with it,
  681. that is displayed. If the method was loaded from an external XPL file, the
  682. file path and modification-time are also displayed.
  683.  
  684. =back
  685.  
  686. The primary purpose of this status system is to allow for checking the
  687. availability and sanity of the RPC servers themselves. For example, if a
  688. server is configured to auto-load methods, and automatically check for
  689. updates, the status system could confirm that a method is available or is at
  690. the correct version.
  691.  
  692. (Note that auto-loading and auto-updating are done on demand, when a call is
  693. made to the method in question. Thus, the status might not reflect changes
  694. until at least one call has been made. Further, if there are very many child
  695. processes handling the RPC servers, several calls may be necessary to ensure
  696. that the child process answering the status request also has the most
  697. up-to-date impression of the server.)
  698.  
  699. =head1 SUBCLASSING AND EXTENDING
  700.  
  701. This package is implemented as a method handler for Apache/mod_perl. This
  702. means that is should be relatively easy to subclass this package to implement
  703. an extended version of status reporting, or to provide handlers for phases of
  704. the request lifecycle not otherwise addressed.
  705.  
  706. =head2 Class Methods
  707.  
  708. There are three class methods defined in this package. One is the constructor,
  709. the other two are handlers for specific phases in the Apache request
  710. lifecycle.
  711.  
  712. =over 4
  713.  
  714. =item new(CLASS, ARGS)
  715.  
  716. This creates a new object of this class and returns a reference to it. The
  717. first argument is the class being created into, the remaining arguments are
  718. treated as key/value pairs (note: not a hash reference). At present, the only
  719. additional argument recognized is:
  720.  
  721. =over 8
  722.  
  723. =item serverclass
  724.  
  725. This is used when the status monitor is being used with a server class other
  726. than B<Apache::RPC::Server> directly. Because several methods from that class
  727. are invoked, it is presumed that the class named here is a subclass of
  728. B<Apache::RPC::Server>. If not, the status monitor may not work correctly, or
  729. at all. In the absence of this value, C<Apache::RPC::Server> is assumed. This
  730. value may also be set with the mod_perl B<PerlSetVar> directive. See the
  731. documentation for C<init_handler>, below.
  732.  
  733. =back
  734.  
  735. =item handler(CLASS, REQUEST)
  736.  
  737. This is the primary entry-point for the package. This is the handler defined
  738. for assignment to C<PerlHandler> in a location configuration block. It is
  739. invoked by mod_perl as a method handler, thus the first argument is either the
  740. name of the class (in the case of class-method, or static, invocation) or the
  741. object configured as the handler. The second argument is the Apache request
  742. object itself.
  743.  
  744. This method derives the query parameters for the request from the Apache
  745. object, and treats them according to the type of information screen requested:
  746.  
  747. =over 8
  748.  
  749. =item screen
  750.  
  751. This specifies which screen of the status monitor is to be displayed. In
  752. absence, the value defaults to "main", which is the internal identifier for
  753. the primary screen of the status monitor system. If the value of this
  754. parameter does not match a known interface hook, then the handler will signify
  755. to mod_perl that it cannot handler the request, by replying with the
  756. C<B<DECLINED>> response code.
  757.  
  758. =item server
  759.  
  760. When the B<screen> parameter is set to C<server>, the monitor displays the
  761. server detail screen. In that case, this parameter specifies which server
  762. should be displayed. Servers are given unique identifiers when they are
  763. created, usually derived from the URL path that they are attached to. If the
  764. value here does not match any known servers, a warning is sent to the browser.
  765.  
  766. =item method
  767.  
  768. When the B<screen> parameter is set to C<method>, this calls for the method
  769. detail screen. The provided interface hook to deal with these requests looks
  770. for both the B<server> parameter above and this one, which specifies by name
  771. the method to be laid out in detail. As with the B<server> parameter, if the
  772. value in this parameter does not match any known data, an error is reported to
  773. the browser.
  774.  
  775. =back
  776.  
  777. Any additional parameters will be preserved by B<make_url> call detailed
  778. below. These are merely the specific ones recognized by the status monitor as
  779. written.
  780.  
  781. =item init_handler(CLASS, REQUEST)
  782.  
  783. This is a very simple handler designed for the B<PerlChildInitHandler>
  784. phase. At present, it only does one simple task (and thus makes no direct use
  785. of either parameter passed to it by mod_perl). However, it is included mainly
  786. as a placeholder for possible future expansion. The current behavior is to
  787. check for the existence of directory-configuration item called C<ServerClass>,
  788. and record the value if it is set. This is used to specifiy the class from
  789. which the RPC server objects are created, if something other than
  790. B<Apache::RPC::Server>. If this information is passed via the C<serverclass>
  791. parameter to the B<new> method above, that value overrides any value
  792. here. However, that requires actually creating an object to use as the
  793. handler, whereas this handler may be used directly, as a static handler. It
  794. would be configured outside of any E<lt>LocationE<gt> blocks, a requirement
  795. for the B<PerlChildInitHandler> phase. It is designed to stack cleanly with
  796. any other handlers for that phase, provided your mod_perl installation
  797. supports stacked handlers.
  798.  
  799. =back
  800.  
  801. =head2 Additional Methods
  802.  
  803. In addition to the class methods above, the following are provided. In most
  804. cases, these do not rely on any data contained within the actual object
  805. itself. Many may also be called as static methods (these are so noted). They
  806. are provided as a utility, implemented as methods so as to avoid namespace
  807. issues:
  808.  
  809. =over 4
  810.  
  811. =item version
  812.  
  813. (May be called as a static method.) Returns the current version of this
  814. module.
  815.  
  816. =item apache_status_attach
  817.  
  818. Attach the B<Apache::RPC::Status> module to the main screen of the
  819. B<Apache::Status> display.
  820.  
  821. =item default_object
  822.  
  823. (May be called as a static method.) Returns a default B<Apache::RPC::Status>
  824. instance when called as a static method. Returns the calling reference itself,
  825. otherwise.
  826.  
  827. =item header(REQUEST, TITLE)
  828.  
  829. Produces the HTML header for a page. Uses the passed-in title parameter to
  830. give the page a title, and extracts any request-specific information from the
  831. B<Apache> request object passed as the first parameter.
  832.  
  833. =item footer(REQUEST)
  834.  
  835. Produces the HTML footer.
  836.  
  837. =item make_url(QUERY|REQUEST, FLAG)
  838.  
  839. (May be called as a static method.) This creates a URL string for use as a
  840. hyperlink. It makes certain to preserve all parameters in a CGI-like
  841. fashion. Additionally, it can make the URL in such a fashion as to allow
  842. better integration with the B<Apache::Status> package. If the C<FLAG>
  843. parameter is passed and is any true value, then the resulting URL will be
  844. tailored for use with B<Apache::Status>. The first argument must be either the
  845. original request object as passed by mod_perl, or a reference to a CGI object
  846. created from the request (see L<CGI> for more on the CGI class).
  847.  
  848. =item main_screen(REQUEST, QUERY, INTERNAL)
  849.  
  850. Renders the HTML (minus the header and footer) for the main screen. The
  851. arguments are the B<Apache> request object, a B<CGI> query object created
  852. from the request, and a boolean flag indicating whether the call into this
  853. method was made from within this module or made from the B<Apache::Status>
  854. page.
  855.  
  856. =item server_summary(SERVER)
  857.  
  858. Creates an HTML snippet to provide a summary for the server passed in as an
  859. argument. The passed-in value should be the server object, not the name.
  860.  
  861. =item server_detail(REQUEST, QUERY, INTERNAL)
  862.  
  863. Renders the HTML (minus header and footer) for a screen describing a server
  864. instance in detail. The server is specified by name in the query parameters.
  865. The arguments are the same as for C<main_screen>.
  866.  
  867. =item method_summary(SERVER, METHOD, BASEURL)
  868.  
  869. Creates and HTML snippet to provide a summary for the specified method of the
  870. specified server. The third argument is a base-URL to use for making links to
  871. the detailed method page.
  872.  
  873. =item method_detail(REQUEST, QUERY, INTERNAL)
  874.  
  875. Renders the HTML (minus header and footer) for a screen describing a method on
  876. a specific server instance, in detail. The method and server are specified by
  877. name in the query parameters. The arguments are the same as for
  878. C<main_screen>.
  879.  
  880. =back
  881.  
  882. =head2 Use and Extension Within Perl Sections
  883.  
  884. Some extension may be done without necessarily subclassing this package. The
  885. class object are implemented simply as hash references. When a request is
  886. received, the B<screen> parameter (see above) is extracted, and used to look
  887. up in the hash table. If there is a value for that key, the value is assumed
  888. to be a hash reference with at least two keys (described below). If it does
  889. not exist, the handler routine declines to handle the request. Thus, some
  890. degree of extension may be done without the need for developing a new class,
  891. if the configuration and manipulation are done within E<lt>PerlE<gt>
  892. configuration blocks.
  893.  
  894. Adding a new screen means writing a routine to handle the requests, and then
  895. adding a hook into that routine to the object that is the handler for the
  896. Apache location that serves RPC status requests. The routines that are written
  897. to handle a request should expect four arguments (in order):
  898.  
  899. =over 4
  900.  
  901. =item The object reference for the location handler
  902.  
  903. =item The Apache request object reference
  904.  
  905. =item A query object reference (see below)
  906.  
  907. =item A flag that is only passed when called from Apache::Status
  908.  
  909. =back
  910.  
  911. The routines are given both the original request object and a query object
  912. reference for sake of ease. The query object is already available prior to the
  913. dispatch, so there is no reason to have each hook routine write the same few
  914. lines to derive a query object from an Apache request. At the same time, the
  915. hooks themselves may need the Apache object to call methods on. The query
  916. object is an instance of B<CGI>. The flag parameter is passed by the linkage
  917. from this status package to B<Apache::Status>. The primary use for it is to
  918. pass to routines such as B<make_url> that are sensitive to the
  919. B<Apache::Status> context.
  920.  
  921. The return value from these routines must be a reference to a list of lines of
  922. text. It is passed to the B<print> method of the B<Apache> class. This is
  923. necessary for compatibility with the B<Apache::Status> environment.
  924.  
  925. To add a new hook, merely assign it to the object directly. The key is the
  926. value of the C<screen> parameter defined above, and the value is a hash
  927. reference with two keys:
  928.  
  929. =over 4
  930.  
  931. =item title
  932.  
  933. A string that is incorporated into the HTML title for the page.
  934.  
  935. =item call
  936.  
  937. A reference to a subroutine or closure that implements the hook, and conforms
  938. to the conventions described above.
  939.  
  940. =back
  941.  
  942. A sample addition:
  943.  
  944.     $stat_obj->{dbi} = {
  945.                            title => 'RPC-side DBI Pool',
  946.                            call  => \&show_dbi_pool
  947.                        };
  948.  
  949. =head1 INTEGRATION WITH Apache::Status
  950.  
  951. This package is designed to integrate with the B<Apache::Status> package that
  952. is a part of mod_perl. However, this is not currently functional. When this
  953. has been debugged, the details will be presented here.
  954.  
  955. =head1 CAVEATS
  956.  
  957. This is the newest part of the RPC-XML package. While the package as a whole
  958. is now considered beta, this piece may yet undergo some alpha-like
  959. enhancements to the interface and such. However, the design and planning of
  960. this were carefully considered, so any such changes should be minimal.
  961.  
  962. =head1 LICENSE
  963.  
  964. This module and the code within are released under the terms of the Artistic
  965. License 2.0
  966. (http://www.opensource.org/licenses/artistic-license-2.0.php). This code may
  967. be redistributed under either the Artistic License or the GNU Lesser General
  968. Public License (LGPL) version 2.1
  969. (http://www.opensource.org/licenses/lgpl-license.php).
  970.  
  971. =head1 SEE ALSO
  972.  
  973. L<Apache::Status>, L<Apache::RPC::Server>, L<RPC::XML::Method>
  974.  
  975. =head1 AUTHOR
  976.  
  977. Randy J. Ray <rjray@blackperl.com>
  978.  
  979. =cut
  980.  
  981.